const jwt = require("jsonwebtoken"); // 导入 JWT 生成token字符串
const { jwtSecretKey, accessExpiresIn, refreshExpiresIn } = require("../../../config"); // token时效
const bcrypt = require("bcryptjs"); // 导入 bcryptjs 明文密码加密
const { mysql } = require("../../db"); // 导入数据库操作模块
const nodemailer = require("nodemailer"); // 导入邮箱验证码发送

exports.Register = async (req, res) => {
	const { username, password, email, code } = req.body;
	const info = [username, password, email, code];

	try {
		const sqlStr = "SELECT * FROM userinfo WHERE username = ? OR email = ?";
		const [results] = await mysql.query(sqlStr, [username, email]);

		if (results.length > 0) return res.error("用户名或邮箱已被占用，请更换!");

		// 调用 bcrypt.hashSync() 对密码进行加密
		password = bcrypt.hashSync(password, 10);

		const sql = "insert into userinfo set ?";
		const [insertResults] = await mysql.query(sql, info);

		if (insertResults.affectedRows !== 1) return res.error("注册用户失败，请稍后再试!");

		return res.success("注册成功!");
	} catch (err) {
		return res.error(err);
	}
};

exports.Code = (req, res) => {
	try {
		// 查询邮箱是否被占用
		const { email } = req.body;
		// 获取当前时间
		var time = new Date();
		// 生成四位随机数
		var str = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
		var code = "";
		function randomNum(min, max) {
			return Math.floor(Math.random() * (max - min) + min);
		}
		for (var i = 1; i <= 6; i++) {
			var txt = str[randomNum(0, str.length)];
			code = code + txt;
		}

		// 发送邮箱验证码
		let transporter = nodemailer.createTransport({
			host: "smtp.163.com",
			port: 465, // SMTP 端口
			auth: {   //发送者的账户和授权码
				user: "15576730892@163.com", //账户
				pass: "LRTYRUNEMKHWLVZS", //smtp授权码，到邮箱设置下获取
			}
		});
		let mailOptions = {
			from: "15576730892@163.com", // 发送者昵称和地址
			to: email, // 接收者的邮箱地址
			subject: "次元人验证码", // 邮件主题
			html: `
        <div align="center" style="font-size: 20px;">
            <div style="padding: 20px 0;color: #333;background-color: #ddd1dd;border-radius: 4px;">
                <span>${code}</span>
            </div>
            <p>此验证码<b>1分钟</b>内有效</p>
        </div>
        `
		};
		//发送邮件
		transporter.sendMail(mailOptions, (error, info) => {
			res.write("邮件发送成功 ID：", info.messageId);
		});
		res.success("验证码发送成功！");
	} catch (err) {
		res.error(err);
	}
};

exports.Login = async (req, res) => {
	const { username, password } = req.body;

	try {
		const sqlStr1 = "SELECT * FROM userinfo WHERE username = ? OR email = ?";
		const [results1] = await mysql.query(sqlStr1, [username, username]);

		if (results1.length !== 1) return res.error("用户名或密码错误!");

		// 判断密码是否正确
		const compareResult = bcrypt.compareSync(password, results1[0].password);
		if (!compareResult) return res.error("用户名或密码错误!");

		// 从用户数据中移除密码
		const { password: _, ...userData } = results1[0];

		// 在服务器端生成Access Token的字符串
		const accessToken = jwt.sign(userData, jwtSecretKey, { expiresIn: accessExpiresIn });

		// 生成Refresh Token
		const refreshToken = jwt.sign(userData, jwtSecretKey, { expiresIn: refreshExpiresIn });

		// 存储Refresh Token（示例代码假设有一个保存Refresh Token的函数）
		await storeRefreshToken(userData.id, refreshToken);

		// 返回成功响应，提供Access Token，并存储Refresh Token（设定为HTTP Only Cookie）
		res.cookie("refreshToken", refreshToken, { httpOnly: true, maxAge: 30 * 24 * 3600000 }); // 设置30天有效

		return res.success("登录成功", { accessToken });
	} catch (err) {
		if (err) {
			if (err.code === "ER_DUP_ENTRY") {
				return res.error("请勿重复登录!");
			} else {
				return res.error(err);
			}
		}
	}
};

const storeRefreshToken = async (userId, refreshToken) => {
	// 更新Refresh Token
	const strSql = `INSERT INTO login_records (uid, refresh_token, date)
                    VALUES (?, ?, NOW())
                    ON DUPLICATE KEY UPDATE refresh_token = ?, date = NOW()`;

	try {
		const [results] = await mysql.query(strSql, [userId, refreshToken, refreshToken]);
		if (results.affectedRows < 1) throw new Error("登录失败，请稍后再试");
	} catch (error) {
		throw error; // 抛出错误让catch捕捉
	}
};

exports.refreshToken = async (req, res) => {
	const { refreshToken } = req.cookies; // 获取Refresh Token

	try {
		// 验证Refresh Token是否有效
		const decoded = jwt.verify(refreshToken, jwtSecretKey);

		// 获取用户全部信息，但排除密码
		const userInfoSql = "SELECT * FROM userinfo WHERE id = ?";
		const [userInfoResults] = await mysql.query(userInfoSql, [decoded.id]);

		if (!userInfoResults.length) {
			return res.error("找不到该用户");
		}

		// 排除密码字段，然后构建新的 Access Token
		const { password, ...userInfoWithoutPassword } = userInfoResults[0];

		// 验证数据库中保存的Refresh Token是否和发送的Refresh Token匹配
		const tokenSql = "SELECT refresh_token FROM login_records WHERE uid = ?";
		const [tokenResults] = await mysql.query(tokenSql, [decoded.id]);

		if (!tokenResults.length || tokenResults[0].refresh_token !== refreshToken) {
			return res.error("Token无效"); // Refresh Token 无效
		}

		// 生成新的 Access Token 和 Refresh Token
		const newAccessToken = jwt.sign(userInfoWithoutPassword, jwtSecretKey, { expiresIn: accessExpiresIn });
		const newRefreshToken = jwt.sign({ id: decoded.id }, jwtSecretKey, { expiresIn: refreshExpiresIn });

		// 更新数据库中的Refresh Token
		await storeRefreshToken(decoded.id, newRefreshToken);

		// 发送新的 Refresh Token 和 Access Token
		res.cookie("refreshToken", newRefreshToken, { httpOnly: true, maxAge: 30 * 24 * 3600 * 1000 });
		res.success({ accessToken: newAccessToken });
	} catch (err) {
		res.error(err);
	}
};


exports.Logout = async (req, res) => {
	try {
		const sqlStr = "DELETE FROM login_records WHERE uid = ?";

		const [results] = await mysql.query(sqlStr, req.user.id);
		if (results.affectedRows !== 1) return res.error("退出登录失败，请先登录!");

		return res.success("退出登录成功,祝您旅途愉快!");
	} catch (err) {
		return res.error(err);
	}
};


